package com.xy.job.admin.repository

import com.xy.job.admin.api.request.JobInstanceQueryParam
import com.xy.job.admin.domain.JobInstance
import com.xy.job.core.enums.JobStatus
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import java.time.LocalDateTime

interface JobInstanceRepository : JpaRepository<JobInstance, Long> {
    @Query(
        """
        select 
              jobInstance.id as id
            , jobInstance.jobId as jobId
            , jobInstance.jobName as jobName
            , jobInstance.groupCode as groupCode
            , jobInstance.jobHandler as jobHandler
            , jobInstance.jobStatus as jobStatus
            , jobInstance.scheduleTime as triggerTime
            , jobInstance.completeTime as completeTime
        from com.xy.job.admin.domain.JobInstance as jobInstance
        where true
          and (jobInstance.groupCode = :#{#param.groupCode} or :#{#param.groupCode} is null or :#{#param.groupCode} = '')
          and (jobInstance.id = :#{#param.jobInstanceId} or :#{#param.jobInstanceId} is null)
          and (jobInstance.jobId = :#{#param.jobId} or :#{#param.jobId} is null)
          and (jobInstance.jobStatus = :#{#param.jobStatus} or :#{#param.jobStatus} is null)
          and (jobInstance.jobHandler = :#{#param.jobHandler} or :#{#param.jobHandler} is null or :#{#param.jobHandler} = '')
    """
    )
    fun findSimplePage(@Param("param") param: JobInstanceQueryParam, pageable: Pageable): Page<Map<String, Any?>>

    fun countByJobIdAndJobStatus(jobId: Long, jobStatus: JobStatus): Int

    @Modifying
    @Query("""
        update 
            com.xy.job.admin.domain.JobInstance as jobInstance
        set 
              jobInstance.jobStatus = 'FAILED'
            , jobInstance.completeTime = :completeTime
            , jobInstance.message = :errorMessage
        where true
            and jobInstance.jobStatus = 'PROCESSING'
            and jobInstance.executorAddress in :nodeAddressList
    """)
    fun markFailedByAddress(nodeAddressList: List<String>, completeTime: LocalDateTime, errorMessage: String)
}